﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BusinessTier
{
    /// <summary>
    /// The GameEvent class defines the properties for wrapper objects for data related to a game event.
    /// </summary>
    public class GameEvent
    {
        /// <summary>
        /// The internal cache of this game event to hold all related event data, 
        /// including key properties such as timestamp, event source and event type.
        /// </summary>
        private IDictionary<string, object> data = new Dictionary<string, object>();

        /// <summary>
        /// Constructs a brand new game event wrapper with the given read-only
        /// timestamp, type and identified event source.
        /// </summary>
        /// <param name="timestamp">the numeric value representing the time the event was registered or occurred</param>
        /// <param name="type">the enumerated value identifying the type of the event</param>
        /// <param name="source">some string representing the source of the event (e.g. the username of the player that raised the event)</param>
        public GameEvent(long timestamp, GameEventType type, string source)
        {
            if (timestamp < 0) throw new ArgumentNullException();
            data["timestamp"] = timestamp;
            data["source"] = source;
            data["type"] = type;
        }

        /// <summary>
        /// Returns the numeric value representing the time the event was
        /// registered or occurred.
        /// </summary>
        public long Timestamp { get { return long.Parse(data["timestamp"].ToString()); } }

        /// <summary>
        /// Returns the enumerated value identifying the type of the event.
        /// </summary>
        public string Source { get { return (string)data["source"]; } }

        /// <summary>
        /// Returns the string representing the source of the event (e.g. the
        /// username of the player that raised the event).
        /// </summary>
        public GameEventType Type { get { return (GameEventType)data["type"]; } }

        /// <summary>
        /// Puts the given data value to the property with the given key name,
        /// overriding the previous data except only if the requested property
        /// key name equals to ignoring case timestamp, type or source.
        /// </summary>
        /// <param name="key">The property key name to put new data to</param>
        /// <param name="value">The new data value to put to this event</param>
        /// <returns>true if and only if the event's properties were successfully changed; false otherwise</returns>
        public bool PutData(string key, object value)
        {
            if (key.ToLower().Equals("timestamp") || key.ToLower().Equals("type") || key.ToLower().Equals("source")) return false;
            else
            {
                data[key.ToLower()] = value;
                return true;
            }
        }

        /// <summary>
        /// Retrieves the data cached for the specified property key name of this event.
        /// </summary>
        /// <param name="key">The property key name to get data for</param>
        public object GetData(string key)
        {
            if (key != null && data.ContainsKey(key)) return data[key];
            else return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IDictionary<string, object> GetAllData()
        {
            return this.data;
        }

        /// <summary>
        /// Returns a string representation of this game event, in JSON compatible format.
        /// </summary>
        /// <returns>a string representation of this game event</returns>
        public override string ToString()
        {
            return "{timestamp: " + Timestamp + ", type: " + Type + ", source: '" + Source + "'}";
        }
    }

    /// <summary>
    /// An enumeration of all of the different possible game event types.
    /// </summary>
    public enum GameEventType
    {
        Start,
        Finish,
        Move,
        Stop,
        Enter,
        Leave
    }
}
